1 Setup

1.1 Load libraries

library(tidyverse)
library(ggdist)
library(ggside)
library(easystats)
library(patchwork)

1.2 Load data


folder <- rstudioapi::selectDirectory(
  caption = "Select Directory",
  label = "Select"
)

df <- read.csv(paste0(folder, '/9_analysis/Online Study/data/preprocessed.csv')) %>% select(-X)
nrow(df)
[1] 12240
length(unique(df$Participant))
[1] 408
df <- df %>% 
  rename("trial_duration" = Video_Time)
names(df)
 [1] "Video"                   "Participant"             "Restoration"            
 [4] "Presence"                "WillingnessToWalk"       "Beauty"                 
 [7] "Structure"               "Interest"                "Familiarity"            
[10] "Scenic"                  "Crowdedness"             "Width"                  
[13] "Valence"                 "Arousal"                 "trial_duration"         
[16] "Distracted_Time"         "stim_screen_1"           "stim_screen_2"          
[19] "stim_screen_3"           "stim_screen_4"           "stim_screen_5"          
[22] "stim_screen_6"           "stim_screen_7"           "stim_screen_8"          
[25] "stim_screen_9"           "stim_screen_10"          "SSA_Mean"               
[28] "covid_1"                 "covid_2"                 "covid_3"                
[31] "covid_4"                 "Concern_Covid_Mean"      "sias1"                  
[34] "sias2"                   "sias3"                   "sias4"                  
[37] "sias5"                   "sias6"                   "SIAS_Total_Mean"        
[40] "sps1"                    "sps2"                    "sps3"                   
[43] "sps4"                    "sps5"                    "sps6"                   
[46] "SPS_Total_Mean"          "Extraversion_1"          "Agreeableness_2"        
[49] "Conscientiousness_3"     "Neuroticism_4"           "Openness_5"             
[52] "Conscientiousness_10"    "Agreeableness_14"        "Neuroticism_16"         
[55] "Extraversion_23"         "HonestyHumility_6_R"     "Extraversion_7_R"       
[58] "Agreeableness_8_R"       "Openness_9_R"            "Conscientiousness_11_R" 
[61] "HonestyHumility_12_R"    "Openness_13_R"           "Neuroticism_15_R"       
[64] "Neuroticism_17_R"        "HonestyHumility_18_R"    "Extraversion_19_R"      
[67] "Agreeableness_20_R"      "Openness_21_R"           "Conscientiousness_22_R" 
[70] "HonestyHumility_24_R"    "ipip_Extroversion"       "ipip_Agreeableness"     
[73] "ipip_Conscientiousness"  "ipip_Neuroticism"        "ipip_Openness"          
[76] "ipip_Honesty"            "crowds_1"                "crowds_2"               
[79] "crowds_3"                "Crowd_Preference_Mean"   "Age"                    
[82] "Background_Architecture" "Background_Arts"         "Background_Rural"       
[85] "Grow.up.country"         "Grow.up.City"            "Lives_now"              
[88] "years_Lives_now"         "NSS"                     "Condition"              
[91] "screen_width"            "screen_height"          
video_data <- read_csv(paste0(folder,"/3_materials/stimuli_scripts/final_set_with_testing_groups_typology_240424.csv"))
Rows: 480 Columns: 22── Column specification ──────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (13): videoname, name_df, name_df_keep, link, quality, rendition, Country, City, prima...
dbl  (9): fps, duration, Cluster, testing_group, n_frames, mean_pedcounts, max_pedcounts, ...
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
length(unique(video_data$videoname))
[1] 480
# add a consistent prefix on columns related to the stimuli (aka 'video')
video_data <- video_data %>% rename_with(.cols = everything(), function(x){
  ifelse(str_starts(x, "video|video_"), 
     paste0("video_", str_remove(x, "video|video_")),
     paste0("video_", x))  }) # v.1.0.4.

names(video_data)
 [1] "video_name"               "video_name_df"            "video_name_df_keep"      
 [4] "video_link"               "video_quality"            "video_rendition"         
 [7] "video_fps"                "video_duration"           "video_Country"           
[10] "video_Cluster"            "video_City"               "video_testing_group"     
[13] "video_primary_category"   "video_secondary_category" "video_n_frames"          
[16] "video_mean_pedcounts"     "video_max_pedcounts"      "video_sum_pedcounts"     
[19] "video_notes"              "video_Location"           "video_Number"            
[22] "video_new_name"          

A total of 408 completed the study in prolific, and watched a total of 480. Many of them faced streaming issues and had low attention scores, let’s develop a strategy to exlude them from analysis.

1.2.1 Join participant response with video metadata


df <- df %>%
    left_join(video_data, by = c("Video" = "video_link"))

1.3 Filtering based on attention metrics

As an indirect measure of attention, during the experiment, we measured the duration (if any) that participants spent interacting with other programs in their computer. Browsers’ javascript API includes the events focus and blur which are fired when the user interacts with the browser. In our case, when a participant clicks on a different browser tab, browser window, or different application, a new row is added in the log with an event = “blur”; when they return to the experiment another event = “focus” is added to the experiment log. We then calculated distracted time specifically for the video presentation trials, as the time interval between a blur and the next focus event, or between a blur and the end a trial (this was necessary for a few cases where the participant returned to the experiment after a video had finished playing).

Below we inspect the data and decide on a filtering strategy.

1.3.1 Length of distractions

We select all video (stimulus presentation) trials that distraction is more than 0, and convert milliseconds to seconds. We can observe there are 149 trials of some distraction out of 12240 total trials.

df |>
  filter(Distracted_Time > 0) |>
  mutate(Distracted_Time = Distracted_Time/1000,
         Distracted_Time= round(Distracted_Time, digits = 0)) |>
  arrange(Distracted_Time) |>
  ggplot( aes(cumsum(Distracted_Time), Distracted_Time)) + 
  geom_line() + 
  geom_point() +
  labs(title=  "Seconds spent away from the experiment window during video trials", x = "Ascending values")

NA
NA

1.3.2 Distracted, in how many videos?

Second, we should examine if these ‘moments of distraction’ happen randomly across participants, or if some participants are consistently not paying attention to the task. So we here we count in how many trials per participant distracted time is above 0. We can see that while some participants are distracted once or twice, others are distracted for 7 or even 27 out 30 video trials.

df |>
  filter(Distracted_Time > 0) |>
  group_by(Participant) |> 
  count() |>
  arrange(n) |>
  pull(n)
 [1]  1  1  1  1  1  1  1  1  1  1  1  1  1  1  2  2  2  2  2  2  2  2  2  3  3  3  5  5  6  6
[31]  7  7 13 13 22 27

1.4 Distraction duration

Let’s look more closely at those participants with no more than 2 distractions. How long where they? They seem to range from minimal (1 second) to severe (5 minutes or 320 seconds).

df |>
  filter(Distracted_Time > 0) |>
  group_by(Participant) |> 
  add_count() |>
  filter( n < 3) |>
  mutate(Distracted_Time = Distracted_Time/1000,
         Distracted_Time= round(Distracted_Time, digits = 0)) |>
  arrange(Distracted_Time) |>
  pull(Distracted_Time)
 [1]   0   1   1   2   2   2   3   3   4   4   4   5   5   6   7   7   9  13  16  17  18  18
[23]  20  24  25  25  31  32  35  62 101 320

1.5 Reasons for distraction

We cannot really know why participants chose to look away from the experiment. However, we know each video should play for 30 seconds, and it can take some seconds to buffer based on the internet connection. We also know that when the connection is bad, a video can take quite some time to load, which could explain why participants switch away from the experiment.

df |>
  filter(Distracted_Time > 0) |>
  mutate(Distracted_Time = Distracted_Time/1000,
         Distracted_Time= round(Distracted_Time, digits = 0)) |>
  group_by(Participant) |> 
  add_count() |>
  filter( n < 3) |>
  ggplot(aes(trial_duration , Distracted_Time)) +
  geom_point() + ggtitle("Is distraction time explained by slow video buffering?")

NA

It’s quite unclear. Even for videos with fast buffering (around 30+ seconds for the entire video trial), participants spend some time distracted.

2 Filtering strategy

Based on the audit above, we concluded the following filtering strategy:

  1. We will remove completely the data from non-attentive participants, defined as anyone who was distracted in more than 2 video trials;
  2. We will remove responses from all trials that participants were distracted at all (i.e. if Distracted Time > 0), but we will keep the rest of their responses.

df_pruned <- df |>
  group_by(Participant) |> 
  mutate( Distracted_n = sum(Distracted_Time > 0)) |>
  filter( Distracted_n < 3) |> # remove participants who were distracted at all for more than 2 videos
  mutate( Distracted_Time = Distracted_Time/1000,
          Distracted_Time= round(Distracted_Time, digits = 0)) |>
  filter( Distracted_Time == 0) # keep only reponses with 0 distraction time

n_distinct(df_pruned$Participant)
[1] 395
df_pruned %>% 
  nrow()
[1] 11819

So after this pruning, we are left with 0 participants.

2.1 Response variance

A second concern we have is if participants responded intentionally, or just ‘clicked-away’… We will assess this by looking at the variance per response item, as well as the deviation from the average.


df_pruned |>
  group_by(Participant) |>
  summarise_at(vars(3:13), function(x) sd(x, na.rm = TRUE)) %>% 
  pivot_longer(cols = 2:12) |>
  ggplot(aes(value, Participant, colour = value < 0.25)) + 
  geom_point() +
  facet_grid(.~name) +
  guides( y = "none")

NA

In the figure above, we can observe that some participants have very low variance on some of the scales. One exception is Presence where many participants don’t have a large variance, but that is to be expected, we have included this parameter as a manipulation check and we expect presence to be stable across trials.

Now we will calculate the average SD across scales for each participant.

df_pruned |>
    group_by(Participant) |>
    summarise_at(vars(3:13), function(x) sd(x, na.rm = TRUE)) %>% 
    pivot_longer(cols = 2:12) |>
    group_by(Participant) %>% 
    summarise(av_value = mean(value)) %>% arrange(av_value) %>% 
    ggplot(aes( av_value, reorder(Participant, av_value)))+ guides(y = "none") + lims(x = c(0, 7)) +
    geom_point()

Here we see that 3 participants specifcally, have consistently low variance in their responses. We will interepret this as being a sign of low-effort and we will remove them.


# save the ids separately
low_effort_ids <- df |>
    group_by(Participant) |>
    summarise_at(vars(3:13), function(x) sd(x, na.rm = TRUE)) %>% 
    pivot_longer(cols = 2:12) |>
    group_by(Participant) %>% 
    summarise(av_value = mean(value)) %>% arrange(av_value) %>% 
    filter(av_value < 0.75) %>% 
    pull(Participant)

length(low_effort_ids)
[1] 3

2.2 Video buffering

We should also remove participant that had severe video streaming problems as this might have influenced their attention and/or appraisals.

df_pruned  %>% 
  ungroup() %>% 
  # filter(trial_duration > 30) %>%
  mutate(duration = if_else(video_duration > 30, 30, video_duration)) %>% # some videos are in fact longer than 30 seconds, but playback was capped at 30 seconds
  mutate(Buffering = trial_duration - video_duration) %>% 
  arrange(Buffering) %>% 
  ggplot(aes(cumsum(Buffering), Buffering, colour = Buffering > 30)) +
  geom_point() +
  guides(x = "none") + 
  labs(title = "Video buffering time per trial" ,subtitle = "Buffering = Playback duration - Video duration")

NA

In the figure above we see that a number of trials show buffering less than 0, which means the trial_duration < video_duration, that indicates some kind of issues with the stimuli presentation. We remove these. We could also be concerned that when the videos take longer to load, participants ‘sense of presence’ dips. Visual inspection (below) suggests that is not the case.

ggplot(df_pruned, aes(trial_duration, Presence) )  + 
  geom_jitter() + geom_smooth(method = "lm") + 
  geom_vline(xintercept = 60, colour = "red", linetype = "dashed") + 
  theme_classic() + 
  labs(title = "Does sense of presence drop with longer video loading times?", subtitle = "It does not like this is an issue")

We should also test if some participants had too many streaming problems which could also influence their responses.


df_pruned %>% 
  group_by(Participant) %>% 
  tally( ) %>% 
  arrange(n) %>% 
  count(n)
Storing counts in `nn`, as `n` already present in input
NA

2.3 Exclude low-effort (i.e. low response stdev)

Finally, we decided to keep videos where excess time (buffering) was less than 2/3 of the video duration, i.e. no more than 20 seconds. This leads to a total of 50 seconds for the whole video duration.

previous_video_count = nrow(df)

df_pruned <- df_pruned |>
  filter(! Participant %in% low_effort_ids)

We define as buffering time. the excess time of each trial, in addition to the duration of the video, in other words time that is attributed to loading the video to the participant’s browser.

\[ (1)~ video~duration + buffering = video~time \] \[ (2)~ buffering = video~time - video~duration \]

Now we will exclude videos:

  1. Where the buffering time exceeds the video duration.
  2. Where the video playback is less than the duration of the video (this would indicate that for some reason the trial was skipped accidentally for some reason.

df_pruned <- df_pruned |>
  mutate(video_duration = if_else(video_duration > 30, 30, video_duration),
         Buffering = trial_duration - video_duration) |>
  filter(Buffering < video_duration,
         video_duration < trial_duration) 

n_distinct( df_pruned$Participant )
[1] 387

One last step, if we have too few trials from a participant, we should also exclude their responses. We create a summary table, showing how many trials we have per participant. We see that 310 participants have full sets (30 trials), but 10 participants have 14 or less trials left after removing videos with streaming issues.

df_pruned %>% 
   group_by(Participant) %>% 
  tally() %>% 
  arrange(n) %>% pull(n) %>% table(.)
.
  4   7   9  10  11  13  14  15  16  18  19  21  23  24  25  26  27  28  29  30 
  1   1   2   1   3   1   1   1   1   1   1   2   1   3   2   1   7  16  31 310 

We keep data from participants with 15 or more valid trials.

ids_to_keep <- df_pruned %>% 
  group_by(Participant) %>% 
  tally() %>% 
  arrange(n) %>% 
  filter(n >=15) %>%  
  pull(Participant)

length(ids_to_keep)
[1] 377
df_pruned <- df_pruned |>
  filter(Participant %in% ids_to_keep)

With this step we dropped -1123 videos.

Following these filtering steps, we now have retained 0 participants out of 408, and we have have kept 11117 video trials, out of 12240.


df_pruned %>%   
  nrow()
[1] 11117

2.4 SUMMARY


length(unique(df$Participant)) # original completed participants
[1] 408
length(unique(df_pruned$Participant)) # original completed participants
[1] 377

2.5 Views per video

df_pruned %>%   
  group_by(Video) %>% 
  tally(name = "n_per_video") %>% 
  arrange(n_per_video) %>% 
  ungroup() %>% 
  summarise(av_n_per_video = mean(n_per_video), 
            sd = sd(n_per_video), 
            range = paste(range(n_per_video), collapse = "-"))

2.6 cleanup

Keep columns we will use later.


names(df_pruned)
  [1] "Video"                    "Participant"              "Restoration"             
  [4] "Presence"                 "WillingnessToWalk"        "Beauty"                  
  [7] "Structure"                "Interest"                 "Familiarity"             
 [10] "Scenic"                   "Crowdedness"              "Width"                   
 [13] "Valence"                  "Arousal"                  "trial_duration"          
 [16] "Distracted_Time"          "stim_screen_1"            "stim_screen_2"           
 [19] "stim_screen_3"            "stim_screen_4"            "stim_screen_5"           
 [22] "stim_screen_6"            "stim_screen_7"            "stim_screen_8"           
 [25] "stim_screen_9"            "stim_screen_10"           "SSA_Mean"                
 [28] "covid_1"                  "covid_2"                  "covid_3"                 
 [31] "covid_4"                  "Concern_Covid_Mean"       "sias1"                   
 [34] "sias2"                    "sias3"                    "sias4"                   
 [37] "sias5"                    "sias6"                    "SIAS_Total_Mean"         
 [40] "sps1"                     "sps2"                     "sps3"                    
 [43] "sps4"                     "sps5"                     "sps6"                    
 [46] "SPS_Total_Mean"           "Extraversion_1"           "Agreeableness_2"         
 [49] "Conscientiousness_3"      "Neuroticism_4"            "Openness_5"              
 [52] "Conscientiousness_10"     "Agreeableness_14"         "Neuroticism_16"          
 [55] "Extraversion_23"          "HonestyHumility_6_R"      "Extraversion_7_R"        
 [58] "Agreeableness_8_R"        "Openness_9_R"             "Conscientiousness_11_R"  
 [61] "HonestyHumility_12_R"     "Openness_13_R"            "Neuroticism_15_R"        
 [64] "Neuroticism_17_R"         "HonestyHumility_18_R"     "Extraversion_19_R"       
 [67] "Agreeableness_20_R"       "Openness_21_R"            "Conscientiousness_22_R"  
 [70] "HonestyHumility_24_R"     "ipip_Extroversion"        "ipip_Agreeableness"      
 [73] "ipip_Conscientiousness"   "ipip_Neuroticism"         "ipip_Openness"           
 [76] "ipip_Honesty"             "crowds_1"                 "crowds_2"                
 [79] "crowds_3"                 "Crowd_Preference_Mean"    "Age"                     
 [82] "Background_Architecture"  "Background_Arts"          "Background_Rural"        
 [85] "Grow.up.country"          "Grow.up.City"             "Lives_now"               
 [88] "years_Lives_now"          "NSS"                      "Condition"               
 [91] "screen_width"             "screen_height"            "video_name"              
 [94] "video_name_df"            "video_name_df_keep"       "video_quality"           
 [97] "video_rendition"          "video_fps"                "video_duration"          
[100] "video_Country"            "video_Cluster"            "video_City"              
[103] "video_testing_group"      "video_primary_category"   "video_secondary_category"
[106] "video_n_frames"           "video_mean_pedcounts"     "video_max_pedcounts"     
[109] "video_sum_pedcounts"      "video_notes"              "video_Location"          
[112] "video_Number"             "video_new_name"           "Distracted_n"            
[115] "Buffering"               
df_pruned <- df_pruned %>%
  select(Participant, Restoration, Presence, WillingnessToWalk, Beauty, Structure, Interest, Familiarity, Scenic, Crowdedness, Width, Valence, Arousal, trial_duration, Distracted_Time, SSA_Mean, Concern_Covid_Mean, SIAS_Total_Mean, SPS_Total_Mean, ipip_Extroversion, ipip_Agreeableness, ipip_Conscientiousness, ipip_Neuroticism, ipip_Openness, ipip_Honesty, Crowd_Preference_Mean, NSS, Condition, screen_width, screen_height, video_name, video_name_df, video_name_df_keep, video_quality, video_rendition, video_fps, video_duration, video_Country, video_Cluster, video_City, video_testing_group, video_primary_category, video_secondary_category, video_n_frames, video_mean_pedcounts, video_max_pedcounts, video_sum_pedcounts, Distracted_n, Buffering)
    
   

2.7 Add demographic data

demographics <- read_csv(paste0(folder, "/9_Analysis/Online Study/data/demographics_merged.csv")) 
New names:Rows: 430 Columns: 22── Column specification ──────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (18): Participant, Arts_background, ArtsBg, ArchitectureBackground, ArchBg, Urban_Rura...
dbl  (3): Age, years_Lives_now, Approval_rate
lgl  (1): ...21
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
demographics <- demographics %>% 
  filter(!is.na(Participant)) %>% 
  mutate(
    Employment = if_else(Employment_status %in% c("Full-time", "Part-time") | Student_status == "Yes", "Working/Studying", "Other (e.g., unemployed, retired)"),
    Age_breaks = cut(Age, breaks = c(17.9, 30, 50, 65, 100), labels = c("18–29", "30-49", "50-64", "65+") ),
    Education = if_else(ArchBg == "Yes", "Architecture", if_else(ArtsBg == "Yes", "Arts", "Other")),
    Upbringing_Urban= if_else(tolower(urban_rural_background) == "urban", "Urban", "Other"),
    Upbringing_Rural= if_else(tolower(urban_rural_background) == "rural", "Rural", "Other"),
    Current_Urban = if_else(tolower(urban_rural_now) == "urban", "Urban", "Other")) %>% 
  mutate(
    Upbringing_Urban = factor(Upbringing_Urban, levels = c("Urban", "Other")),
    Current_Urban = factor(Current_Urban, levels = c("Urban", "Other"))
  )

demographics <- demographics %>% 
  select(Participant, Sex, Age, Language, ArtsBg, ArchBg, Language, Employment_status, Nationality, Approval_rate, Ethnicity, Student_status, Employment, Age_breaks, Education, Upbringing_Urban, Upbringing_Rural, Current_Urban)

length(unique(demographics$Participant))
[1] 389
  
  
df_pruned <- df_pruned %>% 
  left_join(demographics, by = "Participant") %>% 
  ungroup()

n_distinct(df_pruned$Participant)
[1] 377
# skimr::skim(df_pruned)

2.8 ANONYMISE PROLIFIC IDS

We will replace the prolific ids with an alphanumeric code, to release this data to open acces (OSF, etc).

```r
new_ids <-
  df_pruned %>% 
  select(Participant) %>% 
  distinct(Participant) %>% 
  mutate(Anonymised_ID = paste0(sample(1:length(unique(df_pruned$Participant)), replace = F), sample(LETTERS, replace = T), sample(LETTERS, replace = T))) 


new_ids %>% 
  distinct(Anonymised_ID)

df_pruned <- df_pruned %>% 
  left_join(new_ids, by = \Participant\) %>% # add anonymised ID based on Prolific ID
  relocate(Anonymised_ID) %>% 
  select(-Participant) # remove Prolific ID


<!-- rnb-source-end -->

<!-- rnb-frame-begin eyJtZXRhZGF0YSI6eyJjbGFzc2VzIjpbInRibF9kZiIsInRibCIsImRhdGEuZnJhbWUiXSwibnJvdyI6Mzc3LCJuY29sIjoxLCJzdW1tYXJ5Ijp7IkEgdGliYmxlIjoiMzc3IMOXIDEifX0sInJkZiI6Ikg0c0lBQUFBQUFBQUEyMllTMjhjUlJTRjI1NGFTQndsUXNxV0JRdkVMazdkVnoxMnhBUUw4a0l4SVk2elFZTTlpVWM0TTVidEtFUml3WTZmQXIrUVpVS1BtYTU3eGlLUzQ2bnVxWEwzMStmY2M2djM3citRclJkYlhkZU51ckM1MlkzRy9jZHUvTk96M1R1bDY0LzBnNDB1ZE5lWHYzL3J2M1Q3OGtEWGZkYi9lcjg2TVNiS0IvZUdBVWM3ZUxBYUJDdVBmaGhPU09LZDNUYUZaYTlOb1pKM2hrR285SGlZRWtpZVBtcnJjam5ZYVlPVW5yNW9DK2YwMGhmTytmRzM3WXp3L2pPL3l2am8vckF5MjhGM2ZzSytlZGhXcnJ5LzQ0dVYzY2Z0RE1VSGUrMk14dWMvdGorai9OeHZ4dmpKY0dsQk05d0EwY1BoeW9Mb3krSENRazY3ZSszdVV5TVpFamxJU1Exa2tOdzRCbVBIeUZKMmZNRFNPUGFBMmE5RFJCdklrS1J4REprY28waHhqS1RGTVVxc0RXTi9UK0ljV1pGalNZMWpNQUdNcW82Uk9UdEdLdFV4Y2kxUC9BbUxDeUdZTll6OVl0RTVKdWM0RnBTa3hPZ2ttVjJTbkNwSU1sWm5LYWJPa21vQmxwS2NKVlZnbVlFbGd5U1pYSktocUtQa1FxNUlKVkNrNWtZeWxOeEFqbENPRWVVWXVYRWNhYU1ZeEZ5TDFVQ0xJZy9CSlE2eGQ2azZSU3JpY2lSdUVNZHMwU2xTZFVHT2hWT2pPS3JBTUlLdnVZQWMxZHpYcE02d3YwTVFKRkZ5UVRLQnI1bk1CVWtaTUFxSkM1SnlkWTdKT1ZJUzBHTjJQWVpzSU1kRVRySkVWMk91RHBKcWNwQ3NHVUQyOVFaOG1wMGtjUUk5Y25Scms4dHhSRkFmbzNOTThFakpNbkNVNkJ6SmtHTVdGMlBOZ05IUTF4bDhUVndCSTlaSEVRTkJaalIyVmF5UGlzYU9ibXdpaFR0UWNMYWtBcUxVNkNXU0NVcGtoYXpKWGlKekFVVm1ySkV4UTQyVUNyNUdVWkpXQ0J1RHNDRXBEZVlJbzBZVEdydUNzYldoSExIYldqQm5Za0tPeVRsS0V1ZkltWUFqRXhUSVZNRlJ6TUNSbldNUUFrbG1rQ1JGQlhQbjZpUUp2TTFWc0VJbUZ5V0dqV0NCNU95cEhWakIzS1dBS0UyQUpKcWJPSUs1aTZNTWhTQnNVdlN3U2JHeERNb05aWkFLSkh1c0lBTWdTUUlrT1JhUGJBTnpFekZrVFVwQU1obVFqQjQyb2JnbWc1UTkxekFtVGN3T2t0ZFNPMGRRWklFeUtaeGZldEV3cUpLeDdudVR3YURJQ2pVeXFtdXlDbWl5VnRla0dJU05SQXh0S28za3lOT21seWM2MjRCanJXRHNDQnc1QWtkQmptS0djUk1odEJPWVc4anJaRCtIUVpONE5TeUFrb2pBM0ZUZDNDQkpyZ1FORUs4MVFBVWFJR0VvbElRd0V5Wk9GSVJwVUNoakFWbG14Sm1na3hTcVdDaXpHNXl3QmRJQ3Nzd0pLaVdFTjFkeldlYnNzcXpZVEpLQ0xDczJRSnBBbG9JR0oyK0JRbUlQSFRWWEpTbTQyeFF6QiszTnRnL2F6MUFyclVBVEpJZ3lRYTJVaUE0dlh1aERLaERmdGhiZldDdjdsaGtpUkVDWkRDekZCR0tIREhZNEVXaFNTVURUWUk5RGZjdnY0Y3FnVEs0VnlxVXdhRk1GdENtb1RYYWZCMDJZNGM0ekZPak5aVTJabEx3WEt0QUx5VnE5dElqQ2pPN3pBalFsQzlCTUtFeUk4UDVyNlBNTSswVk9CVUs4ZU1rTUJoa3VCaTZoQW8wbGE4V0tLUUNUTSs1MFBIdUNRdlJJaXVEemhENFg3ODlEVnMrZURDV1REVXFtR0VxVGZKOFRHRmdTcGpnelEvaUl3d3lsQXN0QzJLS3JaMC9DRkk4S0pWTzlSdytLVzBZaGQwbGhJRmt6a0pRTSs1d1MzZVVFRlpNUzJKeU53ZWFWSUgyd3MxUjB1VUpIUk5rN3kyQ3cxMEdRQWgyNm9zVVRiSFU0UjZpV21RQ2tZanRVUUpSczVPV1NZY1BJR09Oc2hxS0Vla01RUFdLdXlZQTl1akNrT0xIdkdFUEZlaG54SFlaaGo2NkU3ekFpUkk4WmlGSUw5cFlNMjBiQmNvbWlyTGh2akZndnFhTERjZmV0VUM4NU9jekFxRXJZTi9aQmtpRElNWHhFQ1hzaUJab1pkTWxpNFBBWXNWd3VIYjcrWm1zOG43eVpubmVYYjdYYXdadjM1b3Y1K3plejgrblJ6OS9mdnpMait0bmkzZll3NjJiL3MvbEgvOS9IangvK3ZMcjA0Y25rL09yU1cwZVRpOG4ycTdOK2ZqLzZjR1hLcDR2VGk5bGkzay9hWEw1dHU3R2MwUDMzMW0zanl1ZGJ5OTlmLy81RnQvcTM5a2UyNzc2YXZYNTdOajIvMjc3NTFWL1gvdjd5bjl0dC9IbjNmek0zenE0YytPenRmSG12UjNjT2o5L09mNzNEQ3BmUnJRQnNYTDRRYkorWFA4dTcydnk0V3V2RzhOQ25oOGVMMWVkcmg0dVRrOG5wK1hRMUhoMmR6b1pUL2JWdm4wNHVqZ2ZneS9HNzJWRTdzTFU4Y0R5ZHZUNitXQjM1WkRwL1Bac1BhNDFQSnI5TVQxYURXLzNqdW54YTI2ZG5zL2t3WWFzL2VyNTlzYmlZRE4vYjZpOW9PSEw1WUxvUC93S2NDYmxYSVJVQUFBPT0ifQ== -->

<div data-pagedtable="false">
  <script data-pagedtable-source type="application/json">
{"columns":[{"label":["Anonymised_ID"],"name":[1],"type":["chr"],"align":["left"]}],"data":[{"1":"117YA"},{"1":"205YJ"},{"1":"58LO"},{"1":"362BF"},{"1":"123RA"},{"1":"187BA"},{"1":"91MO"},{"1":"13QL"},{"1":"228YB"},{"1":"266QX"},{"1":"376ZF"},{"1":"177ME"},{"1":"332WT"},{"1":"110LD"},{"1":"25YH"},{"1":"115CK"},{"1":"292WB"},{"1":"178FM"},{"1":"210JR"},{"1":"140VS"},{"1":"342VA"},{"1":"152NX"},{"1":"47QL"},{"1":"211KE"},{"1":"34ZT"},{"1":"76FR"},{"1":"96YA"},{"1":"61YJ"},{"1":"36LO"},{"1":"37BF"},{"1":"52RA"},{"1":"238BA"},{"1":"223MO"},{"1":"182QL"},{"1":"334YB"},{"1":"63QX"},{"1":"71ZF"},{"1":"338ME"},{"1":"148WT"},{"1":"309LD"},{"1":"213YH"},{"1":"245CK"},{"1":"286WB"},{"1":"53FM"},{"1":"244JR"},{"1":"227VS"},{"1":"189VA"},{"1":"298NX"},{"1":"333QL"},{"1":"55KE"},{"1":"240ZT"},{"1":"66FR"},{"1":"317YA"},{"1":"300YJ"},{"1":"22LO"},{"1":"269BF"},{"1":"109RA"},{"1":"354BA"},{"1":"198MO"},{"1":"136QL"},{"1":"194YB"},{"1":"73QX"},{"1":"26ZF"},{"1":"217ME"},{"1":"84WT"},{"1":"281LD"},{"1":"41YH"},{"1":"147CK"},{"1":"87WB"},{"1":"8FM"},{"1":"200JR"},{"1":"102VS"},{"1":"4VA"},{"1":"35NX"},{"1":"95QL"},{"1":"233KE"},{"1":"330ZT"},{"1":"364FR"},{"1":"183YA"},{"1":"12YJ"},{"1":"250LO"},{"1":"197BF"},{"1":"326RA"},{"1":"9BA"},{"1":"101MO"},{"1":"28QL"},{"1":"345YB"},{"1":"143QX"},{"1":"201ZF"},{"1":"116ME"},{"1":"212WT"},{"1":"215LD"},{"1":"171YH"},{"1":"313CK"},{"1":"179WB"},{"1":"6FM"},{"1":"163JR"},{"1":"277VS"},{"1":"75VA"},{"1":"261NX"},{"1":"80QL"},{"1":"79KE"},{"1":"196ZT"},{"1":"247FR"},{"1":"125YA"},{"1":"237YJ"},{"1":"126LO"},{"1":"220BF"},{"1":"19RA"},{"1":"1BA"},{"1":"90MO"},{"1":"65QL"},{"1":"157YB"},{"1":"130QX"},{"1":"151ZF"},{"1":"173ME"},{"1":"97WT"},{"1":"259LD"},{"1":"273YH"},{"1":"129CK"},{"1":"192WB"},{"1":"335FM"},{"1":"274JR"},{"1":"294VS"},{"1":"344VA"},{"1":"290NX"},{"1":"114QL"},{"1":"145KE"},{"1":"368ZT"},{"1":"340FR"},{"1":"21YA"},{"1":"69YJ"},{"1":"57LO"},{"1":"78BF"},{"1":"372RA"},{"1":"207BA"},{"1":"239MO"},{"1":"128QL"},{"1":"149YB"},{"1":"256QX"},{"1":"138ZF"},{"1":"7ME"},{"1":"346WT"},{"1":"289LD"},{"1":"44YH"},{"1":"2CK"},{"1":"32WB"},{"1":"106FM"},{"1":"276JR"},{"1":"363VS"},{"1":"271VA"},{"1":"221NX"},{"1":"369QL"},{"1":"322KE"},{"1":"328ZT"},{"1":"31FR"},{"1":"175YA"},{"1":"104YJ"},{"1":"279LO"},{"1":"17BF"},{"1":"293RA"},{"1":"356BA"},{"1":"23MO"},{"1":"336QL"},{"1":"278YB"},{"1":"24QX"},{"1":"288ZF"},{"1":"153ME"},{"1":"312WT"},{"1":"120LD"},{"1":"184YH"},{"1":"81CK"},{"1":"260WB"},{"1":"60FM"},{"1":"42JR"},{"1":"39VS"},{"1":"263VA"},{"1":"231NX"},{"1":"139QL"},{"1":"208KE"},{"1":"56ZT"},{"1":"112FR"},{"1":"366YA"},{"1":"165YJ"},{"1":"202LO"},{"1":"88BF"},{"1":"38RA"},{"1":"64BA"},{"1":"107MO"},{"1":"282QL"},{"1":"370YB"},{"1":"283QX"},{"1":"327ZF"},{"1":"15ME"},{"1":"209WT"},{"1":"72LD"},{"1":"49YH"},{"1":"304CK"},{"1":"93WB"},{"1":"199FM"},{"1":"350JR"},{"1":"307VS"},{"1":"118VA"},{"1":"5NX"},{"1":"224QL"},{"1":"158KE"},{"1":"99ZT"},{"1":"302FR"},{"1":"206YA"},{"1":"365YJ"},{"1":"355LO"},{"1":"190BF"},{"1":"162RA"},{"1":"311BA"},{"1":"352MO"},{"1":"324QL"},{"1":"230YB"},{"1":"111QX"},{"1":"119ZF"},{"1":"3ME"},{"1":"291WT"},{"1":"329LD"},{"1":"218YH"},{"1":"232CK"},{"1":"113WB"},{"1":"166FM"},{"1":"103JR"},{"1":"305VS"},{"1":"308VA"},{"1":"275NX"},{"1":"267QL"},{"1":"319KE"},{"1":"367ZT"},{"1":"16FR"},{"1":"348YA"},{"1":"176YJ"},{"1":"50LO"},{"1":"295BF"},{"1":"77RA"},{"1":"98BA"},{"1":"214MO"},{"1":"296QL"},{"1":"146YB"},{"1":"234QX"},{"1":"216ZF"},{"1":"62ME"},{"1":"45WT"},{"1":"14LD"},{"1":"154YH"},{"1":"121CK"},{"1":"225WB"},{"1":"287FM"},{"1":"258JR"},{"1":"135VS"},{"1":"361VA"},{"1":"301NX"},{"1":"188QL"},{"1":"68KE"},{"1":"156ZT"},{"1":"241FR"},{"1":"134YA"},{"1":"203YJ"},{"1":"320LO"},{"1":"353BF"},{"1":"315RA"},{"1":"108BA"},{"1":"186MO"},{"1":"253QL"},{"1":"161YB"},{"1":"321QX"},{"1":"299ZF"},{"1":"132ME"},{"1":"243WT"},{"1":"339LD"},{"1":"229YH"},{"1":"46CK"},{"1":"195WB"},{"1":"83FM"},{"1":"303JR"},{"1":"316VS"},{"1":"85VA"},{"1":"331NX"},{"1":"150QL"},{"1":"310KE"},{"1":"86ZT"},{"1":"373FR"},{"1":"168YA"},{"1":"169YJ"},{"1":"375LO"},{"1":"172BF"},{"1":"268RA"},{"1":"284BA"},{"1":"59MO"},{"1":"357QL"},{"1":"185YB"},{"1":"249QX"},{"1":"323ZF"},{"1":"127ME"},{"1":"142WT"},{"1":"40LD"},{"1":"360YH"},{"1":"262CK"},{"1":"137WB"},{"1":"74FM"},{"1":"70JR"},{"1":"257VS"},{"1":"351VA"},{"1":"318NX"},{"1":"20QL"},{"1":"122KE"},{"1":"222ZT"},{"1":"133FR"},{"1":"89YA"},{"1":"181YJ"},{"1":"254LO"},{"1":"67BF"},{"1":"204RA"},{"1":"349BA"},{"1":"43MO"},{"1":"131QL"},{"1":"82YB"},{"1":"297QX"},{"1":"337ZF"},{"1":"280ME"},{"1":"11WT"},{"1":"164LD"},{"1":"252YH"},{"1":"191CK"},{"1":"92WB"},{"1":"347FM"},{"1":"246JR"},{"1":"174VS"},{"1":"54VA"},{"1":"18NX"},{"1":"30QL"},{"1":"48KE"},{"1":"160ZT"},{"1":"270FR"},{"1":"371YA"},{"1":"144YJ"},{"1":"285LO"},{"1":"251BF"},{"1":"29RA"},{"1":"264BA"},{"1":"255MO"},{"1":"358QL"},{"1":"10YB"},{"1":"359QX"},{"1":"51ZF"},{"1":"325ME"},{"1":"124WT"},{"1":"94LD"},{"1":"105YH"},{"1":"159CK"},{"1":"141WB"},{"1":"170FM"},{"1":"155JR"},{"1":"248VS"},{"1":"272VA"},{"1":"33NX"},{"1":"180QL"},{"1":"193KE"},{"1":"306ZT"},{"1":"219FR"},{"1":"167YA"},{"1":"343YJ"},{"1":"265LO"},{"1":"27BF"},{"1":"226RA"},{"1":"236BA"},{"1":"314MO"},{"1":"341QL"},{"1":"374YB"},{"1":"377QX"},{"1":"235ZF"},{"1":"100ME"},{"1":"242WT"}],"options":{"columns":{"min":{},"max":[10],"total":[1]},"rows":{"min":[10],"max":[10],"total":[377]},"pages":{}}}
  </script>
</div>

<!-- rnb-frame-end -->

<!-- rnb-chunk-end -->


<!-- rnb-text-begin -->



## EXPORT


<!-- rnb-text-end -->


<!-- rnb-chunk-begin -->


<!-- rnb-source-begin eyJkYXRhIjoiYGBgclxuYGBgclxud3JpdGVfY3N2KGRmX3BydW5lZCwgZmlsZSA9IHBhc3RlMChcXGRhdGEvZGF0YV9wcnVuZWRfZm9yX2FuYWx5c2lzX1xcLCBTeXMuRGF0ZSgpLCBcXC5jc3ZcXCkpXG5gYGBcbmBgYCJ9 -->

```r
```r
write_csv(df_pruned, file = paste0(\data/data_pruned_for_analysis_\, Sys.Date(), \.csv\))

<!-- rnb-source-end -->

<!-- rnb-output-begin eyJkYXRhIjoiV2FybmluZyBtZXNzYWdlczpcbjE6IFVua25vd24gb3IgdW5pbml0aWFsaXNlZCBjb2x1bW46IGBQYXJ0aWNpcGFudGAuIFxuMjogVW5rbm93biBvciB1bmluaXRpYWxpc2VkIGNvbHVtbjogYFBhcnRpY2lwYW50YC4gXG4ifQ== -->

Warning messages: 1: Unknown or uninitialised column: Participant. 2: Unknown or uninitialised column: Participant. ```

LS0tCnRpdGxlOiAiQXR0ZW51YXRpbmcgc3ViamVjdGl2ZSBjcm93ZGluZyB0aHJvdWdoIGJlYXV0eSBhbiBvbmxpbmUgc3R1ZHkgb24gdGhlIGludGVyYWN0aW9uIGJldHdlZW4gZW52aXJvbm1lbnQgYWVzdGhldGljcywgdHlwb2xvZ3kgYW5kIGNyb3dkaW5nIgpzdWJ0aXRsZTogIkRhdGEgcHJ1bmluZyIKb3V0cHV0OiAKICBodG1sX25vdGVib29rOgogICAgdG9jOiB5ZXMKICAgIHRvY19mbG9hdDogeWVzCiAgICB0b2NfY29sbGFwc2VkOiB5ZXMKICAgIHRvY19kZXB0aDogMwogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMKICAgIHRoZW1lOiBsdW1lbgogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwogICAgdG9jX2RlcHRoOiAnMycKICAgIGRmX3ByaW50OiBwYWdlZApkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCmVkaXRvcl9vcHRpb25zOgogIGNodW5rX291dHB1dF90eXBlOiBpbmxpbmUKLS0tCgojIFNldHVwCgpgYGB7ciBzZXR1cCwgZWNobyA9IEZBTFNFLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpCgpvcHRpb25zKGRpZ2l0cyA9IDMpCgpjYWNoZSA8LSBGQUxTRQpmaWcud2lkdGggPC0gc2VlOjpnb2xkZW5fcmF0aW8oNykKZmlnLmhlaWdodCA8LSA3Cgprbml0cjo6b3B0c19jaHVuayRzZXQoCiAgY29sbGFwc2UgPSBUUlVFLAogIGRwaSA9IDQ1MCwKICBmaWcucGF0aCA9ICIuL2ZpZ3VyZXMvIiwKICBmaWcud2lkdGggPSBmaWcud2lkdGgsCiAgZmlnLmhlaWdodCA9IGZpZy5oZWlnaHQKKQpgYGAKCiMjIExvYWQgbGlicmFyaWVzCgpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoZ2dkaXN0KQpsaWJyYXJ5KGdnc2lkZSkKbGlicmFyeShlYXN5c3RhdHMpCmxpYnJhcnkocGF0Y2h3b3JrKQpgYGAKCiMjIExvYWQgZGF0YQoKYGBge3J9Cgpmb2xkZXIgPC0gcnN0dWRpb2FwaTo6c2VsZWN0RGlyZWN0b3J5KAogIGNhcHRpb24gPSAiU2VsZWN0IERpcmVjdG9yeSIsCiAgbGFiZWwgPSAiU2VsZWN0IgopCgpkZiA8LSByZWFkLmNzdihwYXN0ZTAoZm9sZGVyLCAnLzlfYW5hbHlzaXMvT25saW5lIFN0dWR5L2RhdGEvcHJlcHJvY2Vzc2VkLmNzdicpKSAlPiUgc2VsZWN0KC1YKQpucm93KGRmKQpsZW5ndGgodW5pcXVlKGRmJFBhcnRpY2lwYW50KSkKZGYgPC0gZGYgJT4lIAogIHJlbmFtZSgidHJpYWxfZHVyYXRpb24iID0gVmlkZW9fVGltZSkKbmFtZXMoZGYpCgpgYGAKCmBgYHtyLCB9CnZpZGVvX2RhdGEgPC0gcmVhZF9jc3YocGFzdGUwKGZvbGRlciwiLzNfbWF0ZXJpYWxzL3N0aW11bGlfc2NyaXB0cy9maW5hbF9zZXRfd2l0aF90ZXN0aW5nX2dyb3Vwc190eXBvbG9neV8yNDA0MjQuY3N2IikpCmxlbmd0aCh1bmlxdWUodmlkZW9fZGF0YSR2aWRlb25hbWUpKQoKIyBhZGQgYSBjb25zaXN0ZW50IHByZWZpeCBvbiBjb2x1bW5zIHJlbGF0ZWQgdG8gdGhlIHN0aW11bGkgKGFrYSAndmlkZW8nKQp2aWRlb19kYXRhIDwtIHZpZGVvX2RhdGEgJT4lIHJlbmFtZV93aXRoKC5jb2xzID0gZXZlcnl0aGluZygpLCBmdW5jdGlvbih4KXsKICBpZmVsc2Uoc3RyX3N0YXJ0cyh4LCAidmlkZW98dmlkZW9fIiksIAogICAgIHBhc3RlMCgidmlkZW9fIiwgc3RyX3JlbW92ZSh4LCAidmlkZW98dmlkZW9fIikpLAogICAgIHBhc3RlMCgidmlkZW9fIiwgeCkpICB9KSAjIHYuMS4wLjQuCgpuYW1lcyh2aWRlb19kYXRhKQpgYGAKCkEgdG90YWwgb2YgYHIgbGVuZ3RoKHVuaXF1ZShkZiRQYXJ0aWNpcGFudCkpYCBjb21wbGV0ZWQgdGhlIHN0dWR5IGluIHByb2xpZmljLCBhbmQgd2F0Y2hlZCBhIHRvdGFsIG9mIGByIGxlbmd0aCh1bmlxdWUoZGYkVmlkZW8pKWAuIE1hbnkgb2YgdGhlbSBmYWNlZCBzdHJlYW1pbmcgaXNzdWVzIGFuZCBoYWQgbG93IGF0dGVudGlvbiBzY29yZXMsIGxldCdzIGRldmVsb3AgYSBzdHJhdGVneSB0byBleGx1ZGUgdGhlbSBmcm9tIGFuYWx5c2lzLgoKIyMjIEpvaW4gcGFydGljaXBhbnQgcmVzcG9uc2Ugd2l0aCB2aWRlbyBtZXRhZGF0YQoKYGBge3J9CgpkZiA8LSBkZiAlPiUKICAgIGxlZnRfam9pbih2aWRlb19kYXRhLCBieSA9IGMoIlZpZGVvIiA9ICJ2aWRlb19saW5rIikpCgpgYGAKCiMjIEZpbHRlcmluZyBiYXNlZCBvbiBhdHRlbnRpb24gbWV0cmljcwoKQXMgYW4gaW5kaXJlY3QgbWVhc3VyZSBvZiBhdHRlbnRpb24sIGR1cmluZyB0aGUgZXhwZXJpbWVudCwgd2UgbWVhc3VyZWQgdGhlIGR1cmF0aW9uIChpZiBhbnkpIHRoYXQgcGFydGljaXBhbnRzIHNwZW50IGludGVyYWN0aW5nIHdpdGggb3RoZXIgcHJvZ3JhbXMgaW4gdGhlaXIgY29tcHV0ZXIuIEJyb3dzZXJzJyBqYXZhc2NyaXB0IEFQSSBpbmNsdWRlcyB0aGUgZXZlbnRzICpmb2N1cyogYW5kICpibHVyKiB3aGljaCBhcmUgZmlyZWQgd2hlbiB0aGUgdXNlciBpbnRlcmFjdHMgd2l0aCB0aGUgYnJvd3Nlci4gSW4gb3VyIGNhc2UsIHdoZW4gYSBwYXJ0aWNpcGFudCBjbGlja3Mgb24gYSBkaWZmZXJlbnQgYnJvd3NlciB0YWIsIGJyb3dzZXIgd2luZG93LCBvciBkaWZmZXJlbnQgYXBwbGljYXRpb24sIGEgbmV3IHJvdyBpcyBhZGRlZCBpbiB0aGUgbG9nIHdpdGggYW4gZXZlbnQgPSAiYmx1ciI7IHdoZW4gdGhleSByZXR1cm4gdG8gdGhlIGV4cGVyaW1lbnQgYW5vdGhlciBldmVudCA9ICJmb2N1cyIgaXMgYWRkZWQgdG8gdGhlIGV4cGVyaW1lbnQgbG9nLiBXZSB0aGVuIGNhbGN1bGF0ZWQgZGlzdHJhY3RlZCB0aW1lIHNwZWNpZmljYWxseSBmb3IgdGhlIHZpZGVvIHByZXNlbnRhdGlvbiB0cmlhbHMsIGFzIHRoZSB0aW1lIGludGVydmFsIGJldHdlZW4gYSAqYmx1ciogYW5kIHRoZSBuZXh0ICpmb2N1cyogZXZlbnQsIG9yIGJldHdlZW4gYSAqYmx1ciogYW5kIHRoZSBlbmQgYSB0cmlhbCAodGhpcyB3YXMgbmVjZXNzYXJ5IGZvciBhIGZldyBjYXNlcyB3aGVyZSB0aGUgcGFydGljaXBhbnQgcmV0dXJuZWQgdG8gdGhlIGV4cGVyaW1lbnQgYWZ0ZXIgYSB2aWRlbyBoYWQgZmluaXNoZWQgcGxheWluZykuCgpCZWxvdyB3ZSBpbnNwZWN0IHRoZSBkYXRhIGFuZCBkZWNpZGUgb24gYSBmaWx0ZXJpbmcgc3RyYXRlZ3kuCgojIyMgTGVuZ3RoIG9mIGRpc3RyYWN0aW9ucwoKV2Ugc2VsZWN0IGFsbCB2aWRlbyAoc3RpbXVsdXMgcHJlc2VudGF0aW9uKSB0cmlhbHMgdGhhdCBkaXN0cmFjdGlvbiBpcyBtb3JlIHRoYW4gMCwgYW5kIGNvbnZlcnQgbWlsbGlzZWNvbmRzIHRvIHNlY29uZHMuIFdlIGNhbiBvYnNlcnZlIHRoZXJlIGFyZSAxNDkgdHJpYWxzIG9mIHNvbWUgZGlzdHJhY3Rpb24gb3V0IG9mIGByIG5yb3coZGYpYCB0b3RhbCB0cmlhbHMuCgpgYGB7cn0KZGYgfD4KICBmaWx0ZXIoRGlzdHJhY3RlZF9UaW1lID4gMCkgfD4KICBtdXRhdGUoRGlzdHJhY3RlZF9UaW1lID0gRGlzdHJhY3RlZF9UaW1lLzEwMDAsCiAgICAgICAgIERpc3RyYWN0ZWRfVGltZT0gcm91bmQoRGlzdHJhY3RlZF9UaW1lLCBkaWdpdHMgPSAwKSkgfD4KICBhcnJhbmdlKERpc3RyYWN0ZWRfVGltZSkgfD4KICBnZ3Bsb3QoIGFlcyhjdW1zdW0oRGlzdHJhY3RlZF9UaW1lKSwgRGlzdHJhY3RlZF9UaW1lKSkgKyAKICBnZW9tX2xpbmUoKSArIAogIGdlb21fcG9pbnQoKSArCiAgbGFicyh0aXRsZT0gICJTZWNvbmRzIHNwZW50IGF3YXkgZnJvbSB0aGUgZXhwZXJpbWVudCB3aW5kb3cgZHVyaW5nIHZpZGVvIHRyaWFscyIsIHggPSAiQXNjZW5kaW5nIHZhbHVlcyIpCgoKYGBgCgojIyMgRGlzdHJhY3RlZCwgaW4gaG93IG1hbnkgdmlkZW9zPwoKU2Vjb25kLCB3ZSBzaG91bGQgZXhhbWluZSBpZiB0aGVzZSAnbW9tZW50cyBvZiBkaXN0cmFjdGlvbicgaGFwcGVuIHJhbmRvbWx5IGFjcm9zcyBwYXJ0aWNpcGFudHMsIG9yIGlmIHNvbWUgcGFydGljaXBhbnRzIGFyZSBjb25zaXN0ZW50bHkgKipub3QqKiBwYXlpbmcgYXR0ZW50aW9uIHRvIHRoZSB0YXNrLiBTbyB3ZSBoZXJlIHdlIGNvdW50IGluIGhvdyBtYW55IHRyaWFscyBwZXIgcGFydGljaXBhbnQgZGlzdHJhY3RlZCB0aW1lIGlzIGFib3ZlIDAuIFdlIGNhbiBzZWUgdGhhdCB3aGlsZSBzb21lIHBhcnRpY2lwYW50cyBhcmUgZGlzdHJhY3RlZCBvbmNlIG9yIHR3aWNlLCBvdGhlcnMgYXJlIGRpc3RyYWN0ZWQgZm9yIDcgb3IgZXZlbiAyNyBvdXQgMzAgdmlkZW8gdHJpYWxzLgoKYGBge3J9CmRmIHw+CiAgZmlsdGVyKERpc3RyYWN0ZWRfVGltZSA+IDApIHw+CiAgZ3JvdXBfYnkoUGFydGljaXBhbnQpIHw+IAogIGNvdW50KCkgfD4KICBhcnJhbmdlKG4pIHw+CiAgcHVsbChuKQoKYGBgCgojIyBEaXN0cmFjdGlvbiBkdXJhdGlvbgoKTGV0J3MgbG9vayBtb3JlIGNsb3NlbHkgYXQgdGhvc2UgcGFydGljaXBhbnRzIHdpdGggbm8gbW9yZSB0aGFuIDIgZGlzdHJhY3Rpb25zLiBIb3cgbG9uZyB3aGVyZSB0aGV5PyBUaGV5IHNlZW0gdG8gcmFuZ2UgZnJvbSBtaW5pbWFsICgxIHNlY29uZCkgdG8gc2V2ZXJlICg1IG1pbnV0ZXMgb3IgMzIwIHNlY29uZHMpLgoKYGBge3J9CmRmIHw+CiAgZmlsdGVyKERpc3RyYWN0ZWRfVGltZSA+IDApIHw+CiAgZ3JvdXBfYnkoUGFydGljaXBhbnQpIHw+IAogIGFkZF9jb3VudCgpIHw+CiAgZmlsdGVyKCBuIDwgMykgfD4KICBtdXRhdGUoRGlzdHJhY3RlZF9UaW1lID0gRGlzdHJhY3RlZF9UaW1lLzEwMDAsCiAgICAgICAgIERpc3RyYWN0ZWRfVGltZT0gcm91bmQoRGlzdHJhY3RlZF9UaW1lLCBkaWdpdHMgPSAwKSkgfD4KICBhcnJhbmdlKERpc3RyYWN0ZWRfVGltZSkgfD4KICBwdWxsKERpc3RyYWN0ZWRfVGltZSkKYGBgCgojIyBSZWFzb25zIGZvciBkaXN0cmFjdGlvbgoKV2UgY2Fubm90IHJlYWxseSBrbm93IHdoeSBwYXJ0aWNpcGFudHMgY2hvc2UgdG8gbG9vayBhd2F5IGZyb20gdGhlIGV4cGVyaW1lbnQuIEhvd2V2ZXIsIHdlIGtub3cgZWFjaCB2aWRlbyBzaG91bGQgcGxheSBmb3IgMzAgc2Vjb25kcywgYW5kIGl0IGNhbiB0YWtlIHNvbWUgc2Vjb25kcyB0byBidWZmZXIgYmFzZWQgb24gdGhlIGludGVybmV0IGNvbm5lY3Rpb24uIFdlIGFsc28ga25vdyB0aGF0IHdoZW4gdGhlIGNvbm5lY3Rpb24gaXMgYmFkLCBhIHZpZGVvIGNhbiB0YWtlIHF1aXRlIHNvbWUgdGltZSB0byBsb2FkLCB3aGljaCBjb3VsZCBleHBsYWluIHdoeSBwYXJ0aWNpcGFudHMgc3dpdGNoIGF3YXkgZnJvbSB0aGUgZXhwZXJpbWVudC4KCmBgYHtyfQpkZiB8PgogIGZpbHRlcihEaXN0cmFjdGVkX1RpbWUgPiAwKSB8PgogIG11dGF0ZShEaXN0cmFjdGVkX1RpbWUgPSBEaXN0cmFjdGVkX1RpbWUvMTAwMCwKICAgICAgICAgRGlzdHJhY3RlZF9UaW1lPSByb3VuZChEaXN0cmFjdGVkX1RpbWUsIGRpZ2l0cyA9IDApKSB8PgogIGdyb3VwX2J5KFBhcnRpY2lwYW50KSB8PiAKICBhZGRfY291bnQoKSB8PgogIGZpbHRlciggbiA8IDMpIHw+CiAgZ2dwbG90KGFlcyh0cmlhbF9kdXJhdGlvbiAsIERpc3RyYWN0ZWRfVGltZSkpICsKICBnZW9tX3BvaW50KCkgKyBnZ3RpdGxlKCJJcyBkaXN0cmFjdGlvbiB0aW1lIGV4cGxhaW5lZCBieSBzbG93IHZpZGVvIGJ1ZmZlcmluZz8iKQogIApgYGAKCkl0J3MgcXVpdGUgdW5jbGVhci4gRXZlbiBmb3IgdmlkZW9zIHdpdGggZmFzdCBidWZmZXJpbmcgKGFyb3VuZCAzMCsgc2Vjb25kcyBmb3IgdGhlIGVudGlyZSB2aWRlbyB0cmlhbCksIHBhcnRpY2lwYW50cyBzcGVuZCBzb21lIHRpbWUgZGlzdHJhY3RlZC4KCiMgRmlsdGVyaW5nIHN0cmF0ZWd5CgpCYXNlZCBvbiB0aGUgYXVkaXQgYWJvdmUsIHdlIGNvbmNsdWRlZCB0aGUgZm9sbG93aW5nIGZpbHRlcmluZyBzdHJhdGVneToKCjEuICBXZSB3aWxsIHJlbW92ZSBjb21wbGV0ZWx5IHRoZSBkYXRhIGZyb20gbm9uLWF0dGVudGl2ZSBwYXJ0aWNpcGFudHMsIGRlZmluZWQgYXMgYW55b25lIHdobyB3YXMgZGlzdHJhY3RlZCBpbiBtb3JlIHRoYW4gMiB2aWRlbyB0cmlhbHM7CjIuICBXZSB3aWxsIHJlbW92ZSByZXNwb25zZXMgZnJvbSBhbGwgdHJpYWxzIHRoYXQgcGFydGljaXBhbnRzIHdlcmUgZGlzdHJhY3RlZCBhdCBhbGwgKGkuZS4gaWYgKkRpc3RyYWN0ZWQgVGltZSBcPiAwKiksIGJ1dCB3ZSB3aWxsIGtlZXAgdGhlIHJlc3Qgb2YgdGhlaXIgcmVzcG9uc2VzLgoKYGBge3J9CgpkZl9wcnVuZWQgPC0gZGYgfD4KICBncm91cF9ieShQYXJ0aWNpcGFudCkgfD4gCiAgbXV0YXRlKCBEaXN0cmFjdGVkX24gPSBzdW0oRGlzdHJhY3RlZF9UaW1lID4gMCkpIHw+CiAgZmlsdGVyKCBEaXN0cmFjdGVkX24gPCAzKSB8PiAjIHJlbW92ZSBwYXJ0aWNpcGFudHMgd2hvIHdlcmUgZGlzdHJhY3RlZCBhdCBhbGwgZm9yIG1vcmUgdGhhbiAyIHZpZGVvcwogIG11dGF0ZSggRGlzdHJhY3RlZF9UaW1lID0gRGlzdHJhY3RlZF9UaW1lLzEwMDAsCiAgICAgICAgICBEaXN0cmFjdGVkX1RpbWU9IHJvdW5kKERpc3RyYWN0ZWRfVGltZSwgZGlnaXRzID0gMCkpIHw+CiAgZmlsdGVyKCBEaXN0cmFjdGVkX1RpbWUgPT0gMCkgIyBrZWVwIG9ubHkgcmVwb25zZXMgd2l0aCAwIGRpc3RyYWN0aW9uIHRpbWUKCm5fZGlzdGluY3QoZGZfcHJ1bmVkJFBhcnRpY2lwYW50KQoKZGZfcHJ1bmVkICU+JSAKICBucm93KCkKCmBgYAoKU28gYWZ0ZXIgdGhpcyBwcnVuaW5nLCB3ZSBhcmUgbGVmdCB3aXRoIGByIG5fZGlzdGluY3QoZGZfcHJ1bmVkJFBhcnRpY2lwYW50KWAgcGFydGljaXBhbnRzLgoKIyMgUmVzcG9uc2UgdmFyaWFuY2UKCkEgc2Vjb25kIGNvbmNlcm4gd2UgaGF2ZSBpcyBpZiBwYXJ0aWNpcGFudHMgcmVzcG9uZGVkIGludGVudGlvbmFsbHksIG9yIGp1c3QgJ2NsaWNrZWQtYXdheScuLi4gV2Ugd2lsbCBhc3Nlc3MgdGhpcyBieSBsb29raW5nIGF0IHRoZSB2YXJpYW5jZSBwZXIgcmVzcG9uc2UgaXRlbSwgYXMgd2VsbCBhcyB0aGUgZGV2aWF0aW9uIGZyb20gdGhlIGF2ZXJhZ2UuCgpgYGB7cn0KCmRmX3BydW5lZCB8PgogIGdyb3VwX2J5KFBhcnRpY2lwYW50KSB8PgogIHN1bW1hcmlzZV9hdCh2YXJzKDM6MTMpLCBmdW5jdGlvbih4KSBzZCh4LCBuYS5ybSA9IFRSVUUpKSAlPiUgCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSAyOjEyKSB8PgogIGdncGxvdChhZXModmFsdWUsIFBhcnRpY2lwYW50LCBjb2xvdXIgPSB2YWx1ZSA8IDAuMjUpKSArIAogIGdlb21fcG9pbnQoKSArCiAgZmFjZXRfZ3JpZCgufm5hbWUpICsKICBndWlkZXMoIHkgPSAibm9uZSIpCiAKYGBgCgpJbiB0aGUgZmlndXJlIGFib3ZlLCB3ZSBjYW4gb2JzZXJ2ZSB0aGF0IHNvbWUgcGFydGljaXBhbnRzIGhhdmUgdmVyeSBsb3cgdmFyaWFuY2Ugb24gc29tZSBvZiB0aGUgc2NhbGVzLiBPbmUgZXhjZXB0aW9uIGlzICpQcmVzZW5jZSogd2hlcmUgbWFueSBwYXJ0aWNpcGFudHMgZG9uJ3QgaGF2ZSBhIGxhcmdlIHZhcmlhbmNlLCBidXQgdGhhdCBpcyB0byBiZSBleHBlY3RlZCwgd2UgaGF2ZSBpbmNsdWRlZCB0aGlzIHBhcmFtZXRlciBhcyBhIG1hbmlwdWxhdGlvbiBjaGVjayBhbmQgd2UgZXhwZWN0IHByZXNlbmNlIHRvIGJlIHN0YWJsZSBhY3Jvc3MgdHJpYWxzLgoKTm93IHdlIHdpbGwgY2FsY3VsYXRlIHRoZSBhdmVyYWdlIFNEIGFjcm9zcyBzY2FsZXMgZm9yIGVhY2ggcGFydGljaXBhbnQuCgpgYGB7cn0KZGZfcHJ1bmVkIHw+CiAgICBncm91cF9ieShQYXJ0aWNpcGFudCkgfD4KICAgIHN1bW1hcmlzZV9hdCh2YXJzKDM6MTMpLCBmdW5jdGlvbih4KSBzZCh4LCBuYS5ybSA9IFRSVUUpKSAlPiUgCiAgICBwaXZvdF9sb25nZXIoY29scyA9IDI6MTIpIHw+CiAgICBncm91cF9ieShQYXJ0aWNpcGFudCkgJT4lIAogICAgc3VtbWFyaXNlKGF2X3ZhbHVlID0gbWVhbih2YWx1ZSkpICU+JSBhcnJhbmdlKGF2X3ZhbHVlKSAlPiUgCiAgICBnZ3Bsb3QoYWVzKCBhdl92YWx1ZSwgcmVvcmRlcihQYXJ0aWNpcGFudCwgYXZfdmFsdWUpKSkrIGd1aWRlcyh5ID0gIm5vbmUiKSArIGxpbXMoeCA9IGMoMCwgNykpICsKICAgIGdlb21fcG9pbnQoKQoKYGBgCgpIZXJlIHdlIHNlZSB0aGF0IDMgcGFydGljaXBhbnRzIHNwZWNpZmNhbGx5LCBoYXZlIGNvbnNpc3RlbnRseSBsb3cgdmFyaWFuY2UgaW4gdGhlaXIgcmVzcG9uc2VzLiBXZSB3aWxsIGludGVyZXByZXQgdGhpcyBhcyBiZWluZyBhIHNpZ24gb2YgbG93LWVmZm9ydCBhbmQgd2Ugd2lsbCByZW1vdmUgdGhlbS4KCmBgYHtyfQoKIyBzYXZlIHRoZSBpZHMgc2VwYXJhdGVseQpsb3dfZWZmb3J0X2lkcyA8LSBkZiB8PgogICAgZ3JvdXBfYnkoUGFydGljaXBhbnQpIHw+CiAgICBzdW1tYXJpc2VfYXQodmFycygzOjEzKSwgZnVuY3Rpb24oeCkgc2QoeCwgbmEucm0gPSBUUlVFKSkgJT4lIAogICAgcGl2b3RfbG9uZ2VyKGNvbHMgPSAyOjEyKSB8PgogICAgZ3JvdXBfYnkoUGFydGljaXBhbnQpICU+JSAKICAgIHN1bW1hcmlzZShhdl92YWx1ZSA9IG1lYW4odmFsdWUpKSAlPiUgYXJyYW5nZShhdl92YWx1ZSkgJT4lIAogICAgZmlsdGVyKGF2X3ZhbHVlIDwgMC43NSkgJT4lIAogICAgcHVsbChQYXJ0aWNpcGFudCkKCmxlbmd0aChsb3dfZWZmb3J0X2lkcykKCmBgYAoKIyMgVmlkZW8gYnVmZmVyaW5nCgpXZSBzaG91bGQgYWxzbyByZW1vdmUgcGFydGljaXBhbnQgdGhhdCBoYWQgc2V2ZXJlIHZpZGVvIHN0cmVhbWluZyBwcm9ibGVtcyBhcyB0aGlzIG1pZ2h0IGhhdmUgaW5mbHVlbmNlZCB0aGVpciBhdHRlbnRpb24gYW5kL29yIGFwcHJhaXNhbHMuCgpgYGB7cn0KZGZfcHJ1bmVkICAlPiUgCiAgdW5ncm91cCgpICU+JSAKICAjIGZpbHRlcih0cmlhbF9kdXJhdGlvbiA+IDMwKSAlPiUKICBtdXRhdGUoZHVyYXRpb24gPSBpZl9lbHNlKHZpZGVvX2R1cmF0aW9uID4gMzAsIDMwLCB2aWRlb19kdXJhdGlvbikpICU+JSAjIHNvbWUgdmlkZW9zIGFyZSBpbiBmYWN0IGxvbmdlciB0aGFuIDMwIHNlY29uZHMsIGJ1dCBwbGF5YmFjayB3YXMgY2FwcGVkIGF0IDMwIHNlY29uZHMKICBtdXRhdGUoQnVmZmVyaW5nID0gdHJpYWxfZHVyYXRpb24gLSB2aWRlb19kdXJhdGlvbikgJT4lIAogIGFycmFuZ2UoQnVmZmVyaW5nKSAlPiUgCiAgZ2dwbG90KGFlcyhjdW1zdW0oQnVmZmVyaW5nKSwgQnVmZmVyaW5nLCBjb2xvdXIgPSBCdWZmZXJpbmcgPiAzMCkpICsKICBnZW9tX3BvaW50KCkgKwogIGd1aWRlcyh4ID0gIm5vbmUiKSArIAogIGxhYnModGl0bGUgPSAiVmlkZW8gYnVmZmVyaW5nIHRpbWUgcGVyIHRyaWFsIiAsc3VidGl0bGUgPSAiQnVmZmVyaW5nID0gUGxheWJhY2sgZHVyYXRpb24gLSBWaWRlbyBkdXJhdGlvbiIpCiAgCmBgYApJbiB0aGUgZmlndXJlIGFib3ZlIHdlIHNlZSB0aGF0IGEgbnVtYmVyIG9mIHRyaWFscyBzaG93IGJ1ZmZlcmluZyBsZXNzIHRoYW4gMCwgd2hpY2ggbWVhbnMgdGhlIHRyaWFsX2R1cmF0aW9uIDwgdmlkZW9fZHVyYXRpb24sIHRoYXQgaW5kaWNhdGVzIHNvbWUga2luZCBvZiBpc3N1ZXMgd2l0aCB0aGUgc3RpbXVsaSBwcmVzZW50YXRpb24uIFdlIHJlbW92ZSB0aGVzZS4gV2UgY291bGQgYWxzbyBiZSBjb25jZXJuZWQgdGhhdCB3aGVuIHRoZSB2aWRlb3MgdGFrZSBsb25nZXIgdG8gbG9hZCwgcGFydGljaXBhbnRzICdzZW5zZSBvZiBwcmVzZW5jZScgZGlwcy4gVmlzdWFsIGluc3BlY3Rpb24gKGJlbG93KSBzdWdnZXN0cyB0aGF0IGlzIG5vdCB0aGUgY2FzZS4KCmBgYHtyfQpnZ3Bsb3QoZGZfcHJ1bmVkLCBhZXModHJpYWxfZHVyYXRpb24sIFByZXNlbmNlKSApICArIAogIGdlb21faml0dGVyKCkgKyBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iKSArIAogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDYwLCBjb2xvdXIgPSAicmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKyAKICB0aGVtZV9jbGFzc2ljKCkgKyAKICBsYWJzKHRpdGxlID0gIkRvZXMgc2Vuc2Ugb2YgcHJlc2VuY2UgZHJvcCB3aXRoIGxvbmdlciB2aWRlbyBsb2FkaW5nIHRpbWVzPyIsIHN1YnRpdGxlID0gIkl0IGRvZXMgbm90IGxpa2UgdGhpcyBpcyBhbiBpc3N1ZSIpCmBgYAoKV2Ugc2hvdWxkIGFsc28gdGVzdCBpZiBzb21lIHBhcnRpY2lwYW50cyBoYWQgdG9vIG1hbnkgc3RyZWFtaW5nIHByb2JsZW1zIHdoaWNoIGNvdWxkIGFsc28gaW5mbHVlbmNlIHRoZWlyIHJlc3BvbnNlcy4KCmBgYHtyfQoKZGZfcHJ1bmVkICU+JSAKICBncm91cF9ieShQYXJ0aWNpcGFudCkgJT4lIAogIHRhbGx5KCApICU+JSAKICBhcnJhbmdlKG4pICU+JSAKICBjb3VudChuKQogIApgYGAKCiMjIEV4Y2x1ZGUgbG93LWVmZm9ydCAoaS5lLiBsb3cgcmVzcG9uc2Ugc3RkZXYpCgpGaW5hbGx5LCB3ZSBkZWNpZGVkIHRvIGtlZXAgdmlkZW9zIHdoZXJlIGV4Y2VzcyB0aW1lIChidWZmZXJpbmcpIHdhcyBsZXNzIHRoYW4gMi8zIG9mIHRoZSB2aWRlbyBkdXJhdGlvbiwgaS5lLiBubyBtb3JlIHRoYW4gMjAgc2Vjb25kcy4gVGhpcyBsZWFkcyB0byBhIHRvdGFsIG9mIDUwIHNlY29uZHMgZm9yIHRoZSB3aG9sZSB2aWRlbyBkdXJhdGlvbi4KCmBgYHtyfQpwcmV2aW91c192aWRlb19jb3VudCA9IG5yb3coZGYpCgpkZl9wcnVuZWQgPC0gZGZfcHJ1bmVkIHw+CiAgZmlsdGVyKCEgUGFydGljaXBhbnQgJWluJSBsb3dfZWZmb3J0X2lkcykKYGBgCgpXZSBkZWZpbmUgYXMgYnVmZmVyaW5nIHRpbWUuIHRoZSBleGNlc3MgdGltZSBvZiBlYWNoIHRyaWFsLCBpbiBhZGRpdGlvbiB0byB0aGUgZHVyYXRpb24gb2YgdGhlIHZpZGVvLCBpbiBvdGhlciB3b3JkcyB0aW1lIHRoYXQgaXMgYXR0cmlidXRlZCB0byBsb2FkaW5nIHRoZSB2aWRlbyB0byB0aGUgcGFydGljaXBhbnQncyBicm93c2VyLgoKJCQKKDEpfiB2aWRlb35kdXJhdGlvbiArIGJ1ZmZlcmluZyA9IHZpZGVvfnRpbWUKJCQKJCQKKDIpfiBidWZmZXJpbmcgPSB2aWRlb350aW1lIC0gdmlkZW9+ZHVyYXRpb24KJCQKCk5vdyB3ZSB3aWxsIGV4Y2x1ZGUgdmlkZW9zOgoKMS4gIFdoZXJlIHRoZSBidWZmZXJpbmcgdGltZSBleGNlZWRzIHRoZSB2aWRlbyBkdXJhdGlvbi4KMi4gIFdoZXJlIHRoZSB2aWRlbyBwbGF5YmFjayBpcyBsZXNzIHRoYW4gdGhlIGR1cmF0aW9uIG9mIHRoZSB2aWRlbyAodGhpcyB3b3VsZCBpbmRpY2F0ZSB0aGF0IGZvciBzb21lIHJlYXNvbiB0aGUgdHJpYWwgd2FzIHNraXBwZWQgYWNjaWRlbnRhbGx5IGZvciBzb21lIHJlYXNvbi4KCmBgYHtyfQoKZGZfcHJ1bmVkIDwtIGRmX3BydW5lZCB8PgogIG11dGF0ZSh2aWRlb19kdXJhdGlvbiA9IGlmX2Vsc2UodmlkZW9fZHVyYXRpb24gPiAzMCwgMzAsIHZpZGVvX2R1cmF0aW9uKSwKICAgICAgICAgQnVmZmVyaW5nID0gdHJpYWxfZHVyYXRpb24gLSB2aWRlb19kdXJhdGlvbikgfD4KICBmaWx0ZXIoQnVmZmVyaW5nIDwgdmlkZW9fZHVyYXRpb24sCiAgICAgICAgIHZpZGVvX2R1cmF0aW9uIDwgdHJpYWxfZHVyYXRpb24pIAoKbl9kaXN0aW5jdCggZGZfcHJ1bmVkJFBhcnRpY2lwYW50ICkKCmBgYAoKT25lIGxhc3Qgc3RlcCwgaWYgd2UgaGF2ZSB0b28gZmV3IHRyaWFscyBmcm9tIGEgcGFydGljaXBhbnQsIHdlIHNob3VsZCBhbHNvIGV4Y2x1ZGUgdGhlaXIgcmVzcG9uc2VzLiBXZSBjcmVhdGUgYSBzdW1tYXJ5IHRhYmxlLCBzaG93aW5nIGhvdyBtYW55IHRyaWFscyB3ZSBoYXZlIHBlciBwYXJ0aWNpcGFudC4gV2Ugc2VlIHRoYXQgMzEwIHBhcnRpY2lwYW50cyBoYXZlIGZ1bGwgc2V0cyAoMzAgdHJpYWxzKSwgYnV0IDEwIHBhcnRpY2lwYW50cyBoYXZlIDE0IG9yIGxlc3MgdHJpYWxzIGxlZnQgYWZ0ZXIgcmVtb3ZpbmcgdmlkZW9zIHdpdGggc3RyZWFtaW5nIGlzc3Vlcy4KCmBgYHtyfQpkZl9wcnVuZWQgJT4lIAogICBncm91cF9ieShQYXJ0aWNpcGFudCkgJT4lIAogIHRhbGx5KCkgJT4lIAogIGFycmFuZ2UobikgJT4lIHB1bGwobikgJT4lIHRhYmxlKC4pCmBgYAoKV2Uga2VlcCBkYXRhIGZyb20gcGFydGljaXBhbnRzIHdpdGggMTUgb3IgbW9yZSB2YWxpZCB0cmlhbHMuCgpgYGB7cn0KaWRzX3RvX2tlZXAgPC0gZGZfcHJ1bmVkICU+JSAKICBncm91cF9ieShQYXJ0aWNpcGFudCkgJT4lIAogIHRhbGx5KCkgJT4lIAogIGFycmFuZ2UobikgJT4lIAogIGZpbHRlcihuID49MTUpICU+JSAgCiAgcHVsbChQYXJ0aWNpcGFudCkKCmxlbmd0aChpZHNfdG9fa2VlcCkKCmRmX3BydW5lZCA8LSBkZl9wcnVuZWQgfD4KICBmaWx0ZXIoUGFydGljaXBhbnQgJWluJSBpZHNfdG9fa2VlcCkKYGBgCgpXaXRoIHRoaXMgc3RlcCB3ZSBkcm9wcGVkIGByIG5yb3coZGZfcHJ1bmVkKSAtIHByZXZpb3VzX3ZpZGVvX2NvdW50YCB2aWRlb3MuCgpGb2xsb3dpbmcgdGhlc2UgZmlsdGVyaW5nIHN0ZXBzLCB3ZSBub3cgaGF2ZSByZXRhaW5lZCBgciBuX2Rpc3RpbmN0KCBkZl9wcnVuZWQkUGFydGljaXBhbnQgKWAgcGFydGljaXBhbnRzIG91dCBvZiBgciBuX2Rpc3RpbmN0KCBkZiRQYXJ0aWNpcGFudCApYCwgYW5kIHdlIGhhdmUgaGF2ZSBrZXB0IGByIG5yb3coZGZfcHJ1bmVkKWAgdmlkZW8gdHJpYWxzLCBvdXQgb2YgYHIgbnJvdyhkZilgLgoKYGBge3J9CgpkZl9wcnVuZWQgJT4lICAgCiAgbnJvdygpCgpgYGAKCiMjIFNVTU1BUlkKCmBgYHtyfQoKbGVuZ3RoKHVuaXF1ZShkZiRQYXJ0aWNpcGFudCkpICMgb3JpZ2luYWwgY29tcGxldGVkIHBhcnRpY2lwYW50cwpsZW5ndGgodW5pcXVlKGRmX3BydW5lZCRQYXJ0aWNpcGFudCkpICMgb3JpZ2luYWwgY29tcGxldGVkIHBhcnRpY2lwYW50cwoKYGBgCgojIyBWaWV3cyBwZXIgdmlkZW8KCmBgYHtyfQpkZl9wcnVuZWQgJT4lICAgCiAgZ3JvdXBfYnkoVmlkZW8pICU+JSAKICB0YWxseShuYW1lID0gIm5fcGVyX3ZpZGVvIikgJT4lIAogIGFycmFuZ2Uobl9wZXJfdmlkZW8pICU+JSAKICB1bmdyb3VwKCkgJT4lIAogIHN1bW1hcmlzZShhdl9uX3Blcl92aWRlbyA9IG1lYW4obl9wZXJfdmlkZW8pLCAKICAgICAgICAgICAgc2QgPSBzZChuX3Blcl92aWRlbyksIAogICAgICAgICAgICByYW5nZSA9IHBhc3RlKHJhbmdlKG5fcGVyX3ZpZGVvKSwgY29sbGFwc2UgPSAiLSIpKQpgYGAKCiMjIGNsZWFudXAKCktlZXAgY29sdW1ucyB3ZSB3aWxsIHVzZSBsYXRlci4gCgpgYGB7cn0KCm5hbWVzKGRmX3BydW5lZCkKCgpkZl9wcnVuZWQgPC0gZGZfcHJ1bmVkICU+JQogIHNlbGVjdChQYXJ0aWNpcGFudCwgUmVzdG9yYXRpb24sIFByZXNlbmNlLCBXaWxsaW5nbmVzc1RvV2FsaywgQmVhdXR5LCBTdHJ1Y3R1cmUsIEludGVyZXN0LCBGYW1pbGlhcml0eSwgU2NlbmljLCBDcm93ZGVkbmVzcywgV2lkdGgsIFZhbGVuY2UsIEFyb3VzYWwsIHRyaWFsX2R1cmF0aW9uLCBEaXN0cmFjdGVkX1RpbWUsIFNTQV9NZWFuLCBDb25jZXJuX0NvdmlkX01lYW4sIFNJQVNfVG90YWxfTWVhbiwgU1BTX1RvdGFsX01lYW4sIGlwaXBfRXh0cm92ZXJzaW9uLCBpcGlwX0FncmVlYWJsZW5lc3MsIGlwaXBfQ29uc2NpZW50aW91c25lc3MsIGlwaXBfTmV1cm90aWNpc20sIGlwaXBfT3Blbm5lc3MsIGlwaXBfSG9uZXN0eSwgQ3Jvd2RfUHJlZmVyZW5jZV9NZWFuLCBOU1MsIENvbmRpdGlvbiwgc2NyZWVuX3dpZHRoLCBzY3JlZW5faGVpZ2h0LCB2aWRlb19uYW1lLCB2aWRlb19uYW1lX2RmLCB2aWRlb19uYW1lX2RmX2tlZXAsIHZpZGVvX3F1YWxpdHksIHZpZGVvX3JlbmRpdGlvbiwgdmlkZW9fZnBzLCB2aWRlb19kdXJhdGlvbiwgdmlkZW9fQ291bnRyeSwgdmlkZW9fQ2x1c3RlciwgdmlkZW9fQ2l0eSwgdmlkZW9fdGVzdGluZ19ncm91cCwgdmlkZW9fcHJpbWFyeV9jYXRlZ29yeSwgdmlkZW9fc2Vjb25kYXJ5X2NhdGVnb3J5LCB2aWRlb19uX2ZyYW1lcywgdmlkZW9fbWVhbl9wZWRjb3VudHMsIHZpZGVvX21heF9wZWRjb3VudHMsIHZpZGVvX3N1bV9wZWRjb3VudHMsIERpc3RyYWN0ZWRfbiwgQnVmZmVyaW5nKQogICAgCiAgIApgYGAKCiMjIEFkZCBkZW1vZ3JhcGhpYyBkYXRhCgpgYGB7cn0KZGVtb2dyYXBoaWNzIDwtIHJlYWRfY3N2KHBhc3RlMChmb2xkZXIsICIvOV9BbmFseXNpcy9PbmxpbmUgU3R1ZHkvZGF0YS9kZW1vZ3JhcGhpY3NfbWVyZ2VkLmNzdiIpKSAKCmRlbW9ncmFwaGljcyA8LSBkZW1vZ3JhcGhpY3MgJT4lIAogIGZpbHRlcighaXMubmEoUGFydGljaXBhbnQpKSAlPiUgCiAgbXV0YXRlKAogICAgRW1wbG95bWVudCA9IGlmX2Vsc2UoRW1wbG95bWVudF9zdGF0dXMgJWluJSBjKCJGdWxsLXRpbWUiLCAiUGFydC10aW1lIikgfCBTdHVkZW50X3N0YXR1cyA9PSAiWWVzIiwgIldvcmtpbmcvU3R1ZHlpbmciLCAiT3RoZXIgKGUuZy4sIHVuZW1wbG95ZWQsIHJldGlyZWQpIiksCiAgICBBZ2VfYnJlYWtzID0gY3V0KEFnZSwgYnJlYWtzID0gYygxNy45LCAzMCwgNTAsIDY1LCAxMDApLCBsYWJlbHMgPSBjKCIxOOKAkzI5IiwgIjMwLTQ5IiwgIjUwLTY0IiwgIjY1KyIpICksCiAgICBFZHVjYXRpb24gPSBpZl9lbHNlKEFyY2hCZyA9PSAiWWVzIiwgIkFyY2hpdGVjdHVyZSIsIGlmX2Vsc2UoQXJ0c0JnID09ICJZZXMiLCAiQXJ0cyIsICJPdGhlciIpKSwKICAgIFVwYnJpbmdpbmdfVXJiYW49IGlmX2Vsc2UodG9sb3dlcih1cmJhbl9ydXJhbF9iYWNrZ3JvdW5kKSA9PSAidXJiYW4iLCAiVXJiYW4iLCAiT3RoZXIiKSwKICAgIFVwYnJpbmdpbmdfUnVyYWw9IGlmX2Vsc2UodG9sb3dlcih1cmJhbl9ydXJhbF9iYWNrZ3JvdW5kKSA9PSAicnVyYWwiLCAiUnVyYWwiLCAiT3RoZXIiKSwKICAgIEN1cnJlbnRfVXJiYW4gPSBpZl9lbHNlKHRvbG93ZXIodXJiYW5fcnVyYWxfbm93KSA9PSAidXJiYW4iLCAiVXJiYW4iLCAiT3RoZXIiKSkgJT4lIAogIG11dGF0ZSgKICAgIFVwYnJpbmdpbmdfVXJiYW4gPSBmYWN0b3IoVXBicmluZ2luZ19VcmJhbiwgbGV2ZWxzID0gYygiVXJiYW4iLCAiT3RoZXIiKSksCiAgICBDdXJyZW50X1VyYmFuID0gZmFjdG9yKEN1cnJlbnRfVXJiYW4sIGxldmVscyA9IGMoIlVyYmFuIiwgIk90aGVyIikpCiAgKQoKZGVtb2dyYXBoaWNzIDwtIGRlbW9ncmFwaGljcyAlPiUgCiAgc2VsZWN0KFBhcnRpY2lwYW50LCBTZXgsIEFnZSwgTGFuZ3VhZ2UsIEFydHNCZywgQXJjaEJnLCBMYW5ndWFnZSwgRW1wbG95bWVudF9zdGF0dXMsIE5hdGlvbmFsaXR5LCBBcHByb3ZhbF9yYXRlLCBFdGhuaWNpdHksIFN0dWRlbnRfc3RhdHVzLCBFbXBsb3ltZW50LCBBZ2VfYnJlYWtzLCBFZHVjYXRpb24sIFVwYnJpbmdpbmdfVXJiYW4sIFVwYnJpbmdpbmdfUnVyYWwsIEN1cnJlbnRfVXJiYW4pCgpsZW5ndGgodW5pcXVlKGRlbW9ncmFwaGljcyRQYXJ0aWNpcGFudCkpCiAgCiAgCmRmX3BydW5lZCA8LSBkZl9wcnVuZWQgJT4lIAogIGxlZnRfam9pbihkZW1vZ3JhcGhpY3MsIGJ5ID0gIlBhcnRpY2lwYW50IikgJT4lIAogIHVuZ3JvdXAoKQoKbl9kaXN0aW5jdChkZl9wcnVuZWQkUGFydGljaXBhbnQpCgojIHNraW1yOjpza2ltKGRmX3BydW5lZCkKYGBgCiMjIEFOT05ZTUlTRSBQUk9MSUZJQyBJRFMKV2Ugd2lsbCByZXBsYWNlIHRoZSBwcm9saWZpYyBpZHMgd2l0aCBhbiBhbHBoYW51bWVyaWMgY29kZSwgdG8gcmVsZWFzZSB0aGlzIGRhdGEgdG8gb3BlbiBhY2NlcyAoT1NGLCBldGMpLgpgYGB7cn0KCm5ld19pZHMgPC0KICBkZl9wcnVuZWQgJT4lIAogIHNlbGVjdChQYXJ0aWNpcGFudCkgJT4lIAogIGRpc3RpbmN0KFBhcnRpY2lwYW50KSAlPiUgCiAgbXV0YXRlKEFub255bWlzZWRfSUQgPSBwYXN0ZTAoc2FtcGxlKDE6bGVuZ3RoKHVuaXF1ZShkZl9wcnVuZWQkUGFydGljaXBhbnQpKSwgcmVwbGFjZSA9IEYpLCBzYW1wbGUoTEVUVEVSUywgcmVwbGFjZSA9IFQpLCBzYW1wbGUoTEVUVEVSUywgcmVwbGFjZSA9IFQpKSkgCgoKbmV3X2lkcyAlPiUgCiAgZGlzdGluY3QoQW5vbnltaXNlZF9JRCkKCmRmX3BydW5lZCA8LSBkZl9wcnVuZWQgJT4lIAogIGxlZnRfam9pbihuZXdfaWRzLCBieSA9ICJQYXJ0aWNpcGFudCIpICU+JSAjIGFkZCBhbm9ueW1pc2VkIElEIGJhc2VkIG9uIFByb2xpZmljIElECiAgcmVsb2NhdGUoQW5vbnltaXNlZF9JRCkgJT4lIAogIHNlbGVjdCgtUGFydGljaXBhbnQpICMgcmVtb3ZlIFByb2xpZmljIElECgoKYGBgCgoKIyMgRVhQT1JUCgpgYGB7cn0Kd3JpdGVfY3N2KGRmX3BydW5lZCwgZmlsZSA9IHBhc3RlMCgiZGF0YS9kYXRhX3BydW5lZF9mb3JfYW5hbHlzaXNfIiwgU3lzLkRhdGUoKSwgIi5jc3YiKSkKYGBgCg==